package tps12.axwax.client.view;

import tps12.axwax.client.SpanMeasurement;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.HasResizeHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.TextArea;

public class Clue extends Composite
	implements HasResizeHandlers, HasOpenHandlers<Clue> {
	interface MyUiBinder extends UiBinder<FocusPanel, Clue> {}
	private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
	
	public static interface SizeChangedHandler {
		void onSizeChanged(Clue sender, int ems);
	}
	
	SizeChangedHandler handler;

	public Clue(String html) {
		initWidget(uiBinder.createAndBindUi(this));
		
		content.setHTML(html);
	}
	
	@UiHandler("show")
	void handleClick(ClickEvent event) {
		if (edit.isVisible())
			close();
		else {
			edit.setText(notes.getText());
			edit.setVisible(true);
			notes.setVisible(false);
			OpenEvent.fire(this, this);
		}
	}
	
	static Clue last;
	static int startDragIndex = -1;
	
	@UiHandler("content")
	void handleMouseDown(MouseDownEvent event) {
		last = this;
		startDragIndex = SpanMeasurement.getTextCharacterIndexFromLocation(content.getHTML(), ruler,
			event.getX(), event.getY());
		ruler.setInnerHTML(null);
	}
	
	@UiHandler("content")
	void handleMouseUp(MouseUpEvent event) {
		if (last == this && startDragIndex >= 0) {
			int i =
				SpanMeasurement.getTextCharacterIndexFromLocation(content.getHTML(), ruler,
						event.getX(), event.getY());
			int begin = (i < startDragIndex ? i : startDragIndex) - 1;
			int end = begin == i - 1 ? startDragIndex : i;
			ruler.setInnerHTML(content.getHTML());
			SpanMeasurement.trimTextCharacters(ruler, begin, end - begin);
			notes.setText(ruler.getInnerText());
		}
		last = null;
		startDragIndex = -1;
		ruler.setInnerHTML(null);
	}
	
	@UiHandler("focus")
	void handleMouseOver(MouseOverEvent event) {
		if (!edit.isVisible())
			show.setVisible(true);
	}
	
	@UiHandler("focus")
	void handleMouseOut(MouseOutEvent event) {
		if (!edit.isVisible())
			show.setVisible(false);
	}
	
	@UiHandler("edit")
	void handleValueChange(ValueChangeEvent<String> event) {
		notes.setText(edit.getText());
	}
	
	@UiField HTML content;
	@UiField SpanElement ruler;
	@UiField PushButton show;
	@UiField Label notes;
	@UiField TextArea edit;

	@Override
	public HandlerRegistration addResizeHandler(ResizeHandler handler) {
		return addHandler(handler, ResizeEvent.getType());
	}
	
	public HandlerRegistration addOpenHandler(OpenHandler<Clue> handler) {
		return addHandler(handler, OpenEvent.getType());
	}

	public void close() {
		edit.setVisible(false);
		notes.setVisible(true);
		show.setVisible(false);
	}
}